﻿//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
// Exo² samples - Test
// Copyright (C) 2007-2009 Samuel Lacroix and Raphaël Legouge
//
// Distributed under GNU General Public License
// See the License folder of Exo² for details
//
//
// http://www.codeplex.com/exo2 (eng)
//-----------------------------------------------------------------------------

#pragma once
#ifndef TESTER_H
#define TESTER_H


class ITestNotifier
{
    public:
        void Notify(const tstring& TestName, int Line, const tstring& Message);

    private:
        virtual void NotifyVirtual(const tstring& TestName, int Line, const tstring& Message) = 0;
};


class CPhysicsTestNotifier : public ITestNotifier
{
        void NotifyVirtual(const tstring& TestName, int Line, const tstring& Message);
};


// Class de base des tests
class IBasicTest
{
    friend class CTester;
    
    public:    
        typedef std::list<shared_ptr<IBasicTest> > TList;
        
        void Run();
        tstring GetName() const;
    
    protected:
        const shared_ptr<ITestNotifier>& GetNotifier() const;

    private:
        virtual void RunVirtual() = 0;
        virtual tstring GetNameVirtual() const = 0;
        
        shared_ptr<ITestNotifier> pNotifier; 
};


// Class qui va lancer les tests
class CTester
{
    public:
        static CTester& Instance()
        {
                static CTester* pInstance = NULL;
                if (!pInstance)
                    pInstance = new CTester;
                return *pInstance;
        }
        
        void AddTest(const shared_ptr<IBasicTest>& pTest);
                
        void RunAddedTest() const;
        
        void SetNotifier(const shared_ptr<ITestNotifier>& pNotifier) {this->pNotifier = pNotifier;}
                
    private:
        CTester() {}
        ~CTester() {}
        CTester& operator=(const CTester&);
        CTester(const CTester&);
        
        IBasicTest::TList TestList;
        
        void RunTest(const shared_ptr<IBasicTest>& pTest) const;
        
        shared_ptr<ITestNotifier> pNotifier;
};


class CPhysicsOption : public IBasicTest
{
        void RunVirtual();
        tstring GetNameVirtual() const {return _T("CPhysicsOption");}
};


class CPhysicsEmitter : public IBasicTest
{
        void RunVirtual();
        tstring GetNameVirtual() const {return _T("CPhysicsEmitter");}      
};


class CPhysicsManagement : public IBasicTest
{
        void RunVirtual();
        tstring GetNameVirtual() const {return _T("CPhysicsManagement");}
};


class CPhysicsDispatcher : public IBasicTest
{
        void RunVirtual();
        tstring GetNameVirtual() const {return _T("CPhysicsDispatcher");}
        
        class CDetectionFunctor : public Exo2::IDetectionFunctor
        {
            private:
                void Run(const shared_ptr<Exo2::IPhysicalObject>& pObject1, const shared_ptr<Exo2::IPhysicalObject>& pObject2, Exo2::CCollisionDetectionDispatcher::TCollisions* pCollisionList);
                
                size_t* pSensor;
                
            public:
                CDetectionFunctor(Exo2::CPhysicalEngine* pEngine, size_t* pSensor) : IDetectionFunctor(pEngine), pSensor(pSensor) {}
                
        };
        
        
        class CSolVingFunctor : public Exo2::ISolvingFunctor
        {
            private:
                void Run(const Exo2::CBasicCollision& Collision);
                
                size_t* pSensor;
                
            public:
                CSolVingFunctor(Exo2::CPhysicalEngine* pEngine, size_t* pSensor) : ISolvingFunctor(pEngine), pSensor(pSensor) {}
        };
        
        
        class CCustomFreeParticle : public Exo2::CFreeParticle
        {
            public:
                CCustomFreeParticle() : CFreeParticle(true, true, 1., Exo2::MAPI::VECTOR3(0., 0., 0.)) {};
                IMPLEMENT_INDEXABLE_CLASS_FOR_DISPATCHING;
        };
};

 
#endif